import logging
from logging import handlers
from datetime import datetime
from pathlib import Path


__all__ = [
    # Super-special typing primitives.
    'RunnerManager',
]

from typing import Union

from emi.core import DBSource
from emi.core.RunnerManager import RunnerManager
from emi.core.Context import Context
from emi.core.MainEventEngine import MainEventEngine
from emi.core.task import TaskManager


class App(Context):
    DIR_DB_SOURCE = 'dbsource'

    def __init__(self,appDirPath:Union[str,Path] = None):
        super().__init__(MainEventEngine())
        if appDirPath is None:
            home_path = Path.home()
            self._appDirPath:Path = home_path.joinpath("emi-dir")
        elif isinstance(appDirPath,str):
            self._appDirPath:Path = Path(appDirPath)
        else:
            self._appDirPath = appDirPath
        if not self._appDirPath.exists():
            self._appDirPath.mkdir()
        self.engine._app = self
        self.runner_manager:RunnerManager = RunnerManager(self)
        self.task_manager:TaskManager = TaskManager(self)
        self.getDirPath("bar_data")
        self.getDirPath(App.DIR_DB_SOURCE)
        log_path = self._appDirPath.joinpath("emi-dir.log")
        self._logger = App.__create_Filelogger(log_path,self._appDirPath.name)
        base_db_file = self.getFilePath("storage","base.db")
        print(f"app dir: {self._appDirPath}")

    @property
    def root_dir(self):
        return self._appDirPath

    def getRunnerManager(self)->RunnerManager:
        return self.runner_manager

    def getTaskManager(self)->TaskManager:
        return self.task_manager

    def getDirPath(self, dirName,create_if_no_exist =True)->Path:
        dirPath = self._appDirPath.joinpath(dirName)
        if create_if_no_exist and not dirPath.exists():
             dirPath.mkdir()
        return dirPath

    def getFilePath(self, dirName: str, fileName: str)->Path:
        return self.getDirPath(dirName,True).joinpath(fileName)


    def run(self):
        assert not self.engine.is_running()
        self.running = True
        self.engine.run()

    def run_backtest(self,start:datetime, end:datetime = None):
        assert not self.engine.is_running()
        self.running = True
        self.engine.run_backtest(start,end)

    def wait_backtest_finished(self,exit_engine = False):
        """
            exit_engine: 是否结束退出主进程
        """
        self.engine.wait_backtest_finished(exit_engine)

    def log_i(self,tag, msg: str):
        self._logger.info(f"[{self.engine.now()}|{self.is_mainThread()}|{tag}]: {msg}")

    def log_d(self,tag, msg: str):
        self._logger.debug(f"[{self.engine.now()}|{self.is_mainThread()}|{tag}]: {msg}")

    def log_w(self,tag, msg: str):
        self._logger.warn(f"[{self.engine.now()}|{self.is_mainThread()}|{tag}]: {msg}")

    def log_e(self,tag, msg: str):
        self._logger.error(f"[{self.engine.now()}|{self.is_mainThread()}|{tag}]: {msg}")


    def on_main_engine_a_looper_done(self):
        #3has_save_action = self.storage.save()
        pass
        #self.log_i("xxxx",f"on_main_engine_a_looper_done : {has_save_action}")

    @staticmethod
    def __create_Filelogger(log_path, logging_name):
        '''
        配置log
        :param log_path: 输出log路径
        :param logging_name: 记录中name，可随意
        :return:
        '''
        '''
        logger是日志对象，handler是流处理器，console是控制台输出（没有console也可以，将不会在控制台输出，会在日志文件中输出）
        '''
        # 获取logger对象,取名
        logger = logging.getLogger(logging_name)
        # 输出DEBUG及以上级别的信息，针对所有输出的第一层过滤
        logger.setLevel(level=logging.DEBUG)


        # 生成并设置文件日志格式
        formatter = logging.Formatter('%(levelname)s:%(message)s')
        # console相当于控制台输出，handler文件输出。获取流句柄并设置日志级别，第二层过滤
        console = logging.StreamHandler()
        console.setLevel(logging.DEBUG)
        # 为logger对象添加句柄
        logger.addHandler(console)

        # 创建日志分割类型
        rh = handlers.RotatingFileHandler(log_path, encoding='UTF-8',maxBytes=10*1024*1024, backupCount=5)
        # TimedRotatingFileHandler对象自定义日志级别
        rh.setLevel(logging.DEBUG)
        # TimedRotatingFileHandler对象自定义日志级别
        rh.suffix = "%Y_%m_%d_%H_%M_%S.log"
        # TimedRotatingFileHandler对象自定义日志格式
        rh.setFormatter(formatter)
        logger.addHandler(rh)

        return logger


